﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FC.Strings
{
    /// <summary>
    /// 可变栈字符串，输出顺序为输入顺序的反转
    /// </summary>
    public class StackStringBuilder
    {
        #region 字段

        /// <summary>
        /// 用于存储字符串的字符数组
        /// </summary>
        private char[] stackString = null;

        /// <summary>
        /// 默认的增长值
        /// </summary>
        private static int defaultRaiseSize = 1024;

        /// <summary>
        /// 实际每次增长值
        /// </summary>
        private int raiseSize = defaultRaiseSize;

        #endregion

        #region 属性

        /// <summary>
        /// 字符串长度
        /// </summary>
        public int Length { get; set; }

        /// <summary>
        /// 空间大小
        /// </summary>
        public int Size { get; set; }

        #endregion

        #region 构造方法

        /// <summary>
        /// 默认构造函数
        /// </summary>
        public StackStringBuilder() : this(defaultRaiseSize) { }

        /// <summary>
        /// 根据给定的 空间大小size 构造一个 StackStringBuilder 对象
        /// </summary>
        /// <param name="size">给定空间大小</param>
        public StackStringBuilder(int size)
        {
            Length = 0;
            Size = size;
            stackString = new char[Size];
        }

        /// <summary>
        /// 从 string 构造一个 StackStringBuilder 对象
        /// </summary>
        /// <param name="str">字符串</param>
        public StackStringBuilder(string str) : this(str.ToCharArray()) { }

        /// <summary>
        /// 从字符数组构造一个 StackStringBuilder 对象
        /// </summary>
        /// <param name="array">字符数组</param>
        public StackStringBuilder(char[] array) : this(array.Length + defaultRaiseSize)
        {
            Push(array);
        }

        #endregion

        #region 公有方法

        /// <summary>
        /// 添加一个字符数组
        /// </summary>
        /// <param name="array">字符数组</param>
        /// <returns></returns>
        public StackStringBuilder Push(char[] array)
        {
            if (array.Length + Length >= Size)
            {
                Size = array.Length + Length + raiseSize;
                raiseSize = Length + array.Length;
                Length = 0;
                char[] temp = stackString;
                stackString = new char[Size];
                Push(temp);
            }
            Array.Copy(array, 0, stackString, Length, array.Length);
            
            Length += array.Length;

            return this;
        }

        /// <summary>
        /// 添加一个字符串
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns></returns>
        public StackStringBuilder Push(string str)
        {
            return Push(str.ToCharArray());
        }

        /// <summary>
        /// 添加一个字符
        /// </summary>
        /// <param name="c">字符</param>
        /// <returns></returns>
        public StackStringBuilder Push<T>(T obj) where T : struct
        {
            return Push(obj.ToString());
        }

        /// <summary>
        /// 添加一个字符列表
        /// </summary>
        /// <param name="list">字符列表</param>
        /// <returns></returns>
        public StackStringBuilder Push(List<char> list)
        {
            return Push(list.ToArray());
        }

        /// <summary>
        /// 添加一个字符串列表
        /// </summary>
        /// <param name="list">字符串列表</param>
        /// <returns></returns>
        public StackStringBuilder Push(List<string> list)
        {
            foreach (var item in list)
            {
                Push(item);
            }
            return this;
        }

        /// <summary>
        /// 获取创建的字符串
        /// </summary>
        /// <returns>字符串</returns>
        public override string ToString()
        {
            return new string(stackString.Reverse().ToArray(), Size - Length, Length);
        }

        /// <summary>
        /// 输出生成的字符串
        /// </summary>
        /// <returns></returns>
        public string Pop()
        {
            return this.ToString();
        }
        #endregion
    }

}
